using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using TerritoryGame.Domain.Entities;
using TerritoryGame.Domain.ValueObjects;

namespace TerritoryGame.Infrastructure.Persistence;

public class GameDbContext : DbContext
{
    public GameDbContext(DbContextOptions<GameDbContext> options) : base(options)
    {
    }
    
    public DbSet<GameRoom> GameRooms { get; set; }
    public DbSet<Player> Players { get; set; }
    public DbSet<Game> Games { get; set; }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<GameRoom>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.Name).IsRequired().HasMaxLength(100);
            entity.Property(e => e.RoomCode).IsRequired().HasMaxLength(8);
            entity.HasIndex(e => e.RoomCode).IsUnique();
            entity.Property(e => e.Password).HasMaxLength(50);
            entity.Property(e => e.Status).HasConversion<string>();
            entity.Property(e => e.CreatedBy).IsRequired(false); // 添加CreatedBy字段配置
            entity.Property(e => e.CreatedAt).IsRequired();
            entity.Property(e => e.UpdatedAt).IsRequired();
        });
        
        modelBuilder.Entity<Player>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.NickName).IsRequired().HasMaxLength(50);
            entity.Property(e => e.Color).HasConversion(
                v => v.Value,
                v => TerritoryGame.Domain.ValueObjects.PlayerColor.FromString(v));
            entity.Property(e => e.CurrentScore).HasConversion(
                v => v.Value,
                v => new TerritoryGame.Domain.ValueObjects.GameScore(v));
            entity.Property(e => e.LastActiveAt).IsRequired();
        });
        
        modelBuilder.Entity<Game>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.HasOne(e => e.Room).WithMany().HasForeignKey("RoomId");
            entity.Property(e => e.CreatedAt).IsRequired();
            
            // Configure Canvas as owned entity type
            entity.OwnsOne(e => e.Canvas, canvas =>
            {
                canvas.Property(c => c.Width).HasColumnName("CanvasWidth");
                canvas.Property(c => c.Height).HasColumnName("CanvasHeight");
                canvas.Property(c => c.Pixels).HasConversion(
                    v => System.Text.Json.JsonSerializer.Serialize(v, (System.Text.Json.JsonSerializerOptions?)null),
                    v => System.Text.Json.JsonSerializer.Deserialize<Dictionary<Position, PlayerColor>>(v, (System.Text.Json.JsonSerializerOptions?)null) ?? new Dictionary<Position, PlayerColor>()
                ).HasColumnName("CanvasPixels")
                .Metadata.SetValueComparer(new ValueComparer<Dictionary<Position, PlayerColor>>(
                    (c1, c2) => c1!.Count == c2!.Count && c1.All(kvp => c2.ContainsKey(kvp.Key) && c2[kvp.Key].Value == kvp.Value.Value),
                    c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.Key.GetHashCode(), v.Value.GetHashCode())),
                    c => new Dictionary<Position, PlayerColor>(c)
                ));
            });
        });
        
        base.OnModelCreating(modelBuilder);
    }
}
